﻿package net.wangit.jdbc.executable;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.List;

import net.wangit.framework.debug.Recorder;
import net.wangit.jdbc.DB;
import net.wangit.jdbc.DBImplementor;
import net.wangit.jdbc.JDBCException;
import net.wangit.jdbc.table.Column;
import net.wangit.jdbc.table.TableMeta;
import net.wangit.jdbc.table.TableMetaFactory;
import net.wangit.jdbc.util.JDBCExceptionReporter;


public class DeleteRow extends AbstractColumnRow implements Executable {

	private static final long serialVersionUID = 1L;
	private String sonTableName;
	private String[][] linkedFields;

	public DeleteRow() {
		sonTableName = null;
		linkedFields = null;
	}

	public void setLinkedFields(String[][] linkedFields) {
		this.linkedFields = linkedFields;
	}

	public void setSonTableName(String sonTableName) {
		this.sonTableName = sonTableName;
	}

	public void execute(DBImplementor db, TableMeta meta, int[] count,
			String unitId) throws JDBCException {
		net.wangit.jdbc.database.Database database;
		List<Column> primaryKeyColumns;
		String sql;
		PreparedStatement ps;
		database = db.getJDBCSettings().getDatabase();
		primaryKeyColumns = meta.getPrimaryKey().getColumns();
		Column versionColumn = meta.getVersionColumn();
		if (versionColumn != null) {
			boolean isDirty = VersionChecker.isDirty(db, meta
					.getQualifiedName(db), primaryKeyColumns, this,
					versionColumn, versionColumnValue);
			if (isDirty)
				throw new DirtyRowException("the data in this row is dirty");
		}
		if (sonTableName != null)
			deleteSonTable(db, meta.getDomain());
		sql = SQLUtil.toDeleteStatement(meta.getQualifiedName(db),
				primaryKeyColumns);
		ps = null;
		try {
			ps = db.getBatcher().prepareStatement(sql);
			for (int i = 0; i < primaryKeyColumns.size(); i++) {
				Column column = primaryKeyColumns.get(i);
				String value = getPrimaryKey(column.getName());
				column.getSqlType(database).set(ps, value, i + 1);
			}

			count[2] += ps.executeUpdate();
		} catch (SQLException sqle) {
			JDBCExceptionReporter.logExceptions(sqle);
			throw new JDBCException((new StringBuilder("could not delete: "))
					.append(sql).toString(), sqle);
		} finally {
			try {
				db.getBatcher().closeStatement(ps);
			} catch (SQLException sqle) {
				throw new JDBCException("could not close statement", sqle);
			}
		}
		Recorder.countDelete();
	}

	private void deleteSonTable(DB db, String domain) throws JDBCException {
		TableMeta meta = TableMetaFactory.getTableMeta(domain, sonTableName);
		StringBuffer sql = new StringBuffer("delete from ");
		sql.append(sonTableName).append(" where ");
		int count = linkedFields.length;
		String values[] = new String[count];
		int types[] = new int[count];
		for (int i = 0; i < linkedFields.length; i++) {
			String fatherColumnName = linkedFields[i][0];
			String sonColumnName = linkedFields[i][1];
			sql.append(sonColumnName).append("=?");
			if (i < count - 1)
				sql.append(" and ");
			values[i] = getPrimaryKey(fatherColumnName);
			types[i] = meta.getColumn(sonColumnName).getType().code();
		}

		db.execute(sql.toString(), values, types);
	}

	public boolean isInsertRow() {
		return false;
	}

	public boolean isUpdateRow() {
		return false;
	}

	public boolean isDeleteRow() {
		return true;
	}
}
